﻿using System;
using System.Collections.Generic;
using System.Threading;
using ExpertSystem.Interfaces;
using ExpertSystem.IViews;
using ExpertSystem.Views;

namespace ExpertSystem.Domains
{
    public class Variable : IVariable 
    {
        private string _name;
        private readonly bool _inputbyuser;
        private object _value;
        private string _type;
        private string _comment;
        private string _find;
        private bool _isConstant;
        private bool _isGoal;
        private List<string> _possiblevalues;
        private EventHandler _radyForInput;
        private bool _isAsync;
        private EventWaitHandle _event;
        protected bool _valued = false;
        private bool _tryToResolve= false;
        protected bool AppendedValue=false;
        protected bool Init = true;
        public EventHandler DuplicateWay
        {
            get; set;
        }

        public void TryToResolve()
        {
            _tryToResolve = true;
        }

        public void MakeAppended()
        {
            AppendedValue = true;
        }

        public bool AppendableValue
        {
            get { return AppendedValue; }
        }

        public Variable(bool inputbyuser, string comment, string type, List<string> possiblevalues, bool isAsync)
        {
            _inputbyuser = inputbyuser;
            _isAsync = isAsync;
            _possiblevalues = possiblevalues;
            _comment = comment;
            _type = type;
            if (type == "Int")
                _value = 0;
            _event = new AutoResetEvent(false);
        }

        public bool InputByUser
        {
            get { return _inputbyuser; }
        }

        public virtual bool IsFuzzy
        {
            get { return false; }
        }

        #region Implementation of IVariable


        /// <summary>
        /// Имя переменной
        /// </summary>
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public string Coments
        {
            get { return _comment; }
        }

        /// <summary>
        /// Имеет ли значение
        /// </summary>
        /// <returns></returns>
        public bool HaveValue()
        {
            return (_valued || _tryToResolve) && Init;
        }

        /// <summary>
        /// Может ли быть запрошена
        /// </summary>
        /// <returns></returns>
        public bool CanBeResolved()
        {
            return _inputbyuser || _isConstant;
        }

        public virtual object Value
        {
            get { return _value; }
            set
            {
                _valued = true;
                _value = value;
            }
        }

        public string Comment
        {
            get { return _comment; }
            set { _comment = value; }
        }

        public bool IsConstant
        {
            get { return _isConstant; }
            set { _isConstant = value; }
        }

        public bool IsGoal
        {
            get { return _isGoal; }
            set { _isGoal = value; }
        }

        public virtual void Resolve()
        {
            _tryToResolve = true;
            if (AppendedValue)
            {
                //Init = true;
            }
            if (!_isAsync)
            {
                IAsckingVariableForm AsckingVariableForm = new AskingVariableForm(this);
                AsckingVariableForm.ShowDialog();
                
            }
            else
            {
                if (IsFuzzy)
                {
                    DuplicateWay(this, null);
                }
                _radyForInput(this, null);
                _event.Reset();
                _event.WaitOne();
                _find = "";
            }
            //new VariableResolverPresenter()
        }


        public List<string> PosibleValues
        {
            get { return _possiblevalues; }
        }

        public string ValueType
        {
            get { return _type; }
        }

        public EventHandler RadyForInput
        {
            get { return _radyForInput; }
            set { _radyForInput = value; }
        }

        public EventWaitHandle VarInpeted
        {
            get { return _event; }
            set { _event = value; }
        }

        #endregion
    }
}
